package com.beeasy.tools.bean;

import lombok.NonNull;
import ma.glasnost.orika.MapperFactory;

import java.util.*;

/**
 * @author Bin
 */
public class BeanUtil {

    /**
     * features
     */
    public static final int FEATURE_IGNORE_NULL = 0x01;

    //map
    private static MapperFactoryHolder holder = new MapperFactoryHolder(new MapperInitHandlerImpl());
    private static MapperFactoryHolder ignoreHolder = new MapperFactoryHolder(new MapperInitHandlerImpl()).setIgnoreNull(true);

    public static <T> T cast(@NonNull Object src, Class<T> dest){
        return cast(src, dest, null);
    }

    public static <T> T cast(@NonNull Object src, Class<T> dest, Map<String, Object> params, int ...features){
        if (params == null) {
            params = new HashMap<>();
        }
        AbstractMapper.localParams.set(params);
        MapperFactoryHolder holder = null;
        for (int feature : features) {
           if((feature & FEATURE_IGNORE_NULL) > 0){
               holder = ignoreHolder;
           } else {
               holder = BeanUtil.holder;
           }
        }
        if (holder == null) {
            holder = BeanUtil.holder;
        }
        MapperFactory factory = holder.getMapperFactory(src.getClass(), dest);
        if(src instanceof Collection){
            return (T) factory.getMapperFacade().mapAsList((Iterable)src, dest);
        } else {
            return factory.getMapperFacade().map(src, dest);
        }
    }

    public static <T> void assign(T dest, Object src, int ...features) {
        assign(dest, src, null, features);
    }

    public static <T> void assign(T dest, Object src, Map<String,Object> params, int ...features) {
        if (params == null) {
            params = new HashMap<>();
        }
        AbstractMapper.localParams.set(params);
        MapperFactoryHolder holder = null;
        for (int feature : features) {
            if((feature & FEATURE_IGNORE_NULL) > 0){
                holder = ignoreHolder;
            } else {
                holder = BeanUtil.holder;
            }
        }
        if (holder == null) {
            holder = BeanUtil.holder;
        }
        MapperFactory factory = holder.getMapperFactory(src.getClass(), dest.getClass());
        if(src instanceof Collection){
            throw new RuntimeException("not support collection");
        } else {
            factory.getMapperFacade().map(src, dest);
        }
    }

//    private static <F,T> MapperFactory getMapperFactory(Class<F> src, Class<T> dest){
//        MapperFactory factory = holders.computeIfAbsent(dest, k -> {
//            DefaultMapperFactory _factory = new DefaultMapperFactory.Builder().build();
//            return _factory;
//        });
//        initedClasses.computeIfAbsent(src, k -> {
//            ClassMapBuilder builder = factory.classMap(src, dest);
//            //如果有设定mapper
//            MapperEntity mapperEntity = (MapperEntity) dest.getAnnotation(MapperEntity.class);
//            if (mapperEntity != null) {
//                if(mapperEntity.ignoreFields().length > 0) {
//                    for (String s : mapperEntity.ignoreFields()) {
//                        builder.exclude(s);
//                    }
//                }
//            }
//            //获得自定义字段
//            for (Field field : dest.getDeclaredFields()) {
//                MapperField mapperField = field.getAnnotation(MapperField.class);
//                if (mapperField == null) {
//                    continue;
//                }
//                Class<? extends AbstractMapper> mapperClass = mapperField.mapper();
//                factory.getConverterFactory().registerConverter(mapperClass.getName(), new BidirectionalConverter(){
//
//                    @Override
//                    public Object convert(Object o, Type type, MappingContext mappingContext) {
//                        return null;
//                    }
//
//                    @Override
//                    public Object convertTo(Object o, Type type, MappingContext mappingContext) {
//                        return null;
//                    }
//
//                    @Override
//                    public Object convertFrom(Object o, Type type, MappingContext mappingContext) {
//                        return null;
//                    }
//
//                });
//                builder.customize(new CustomMapper() {
//                    @Override
//                    public void mapAtoB(Object o, Object o2, MappingContext context) {
//                        super.mapAtoB(o, o2, context);
//                    }
//                });
////                builder.fieldMap(field.getName(), field.getName())
////                        .converter(mapperClass.getName())
////                        .add();
//            }
//            builder.byDefault()
//                    .register();
//            return Boolean.TRUE;
//        });
//        return factory;
//    }




}
